﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Text;

using Utils;
using Utils.Buffer;

namespace Microsoft.AspNetCore.Mvc
{
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
    public partial class AuthAttribute : Attribute
    {

        public AuthAttribute() : this(true)
        {

        }
        public AuthAttribute(bool isValidate)
        {
            this.IsValidate = isValidate;
        }

        public AuthAttribute(params Type[] userTokens) : this(true)
        {
            UserTokenTypes = userTokens;
        }

        //public virtual string Key { get; } = "Mic.Core";

        public bool IsValidate { get; set; }
        public Type[] UserTokenTypes { get; set; }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="context"></param>
        /// <param name="serviceProvider">请求周期</param>
        public virtual void OnAuthorization(AuthorizationFilterContext context)
        {
            try
            {
                AuthIdentity[] userTokens = context.HttpContext.RequestServices.GetServices<AuthIdentity>().ToArray();
                if (userTokens.IsEmpty())
                {
                    return;
                }

                var result = OnAuthorization(context, userTokens);
                if (result != null)
                {
                    context.Result = new ObjectResult(result);
                }
            }
            catch (Exception e)
            {
                context.Result = new ObjectResult(Result.Fail(e.Message, ErrorType.AuthorizationError));
            }
        }

        private bool Load(HttpContext httpContext, AuthIdentity[] userTokens)
        {
            try
            {

                var authorization = httpContext.Request.GetAuthorizationData();

                if (authorization == null)
                    return false;

                if (authorization.ExpiryTime < DateTime.Now.ToUnixTimestamp())
                {
                    return false;
                }
                foreach (var userToken in userTokens)
                {
                    if (userToken.GetType().Name.Equals(authorization.TypeName))
                    {
                        InjectionFactory.ImportsFormFactory(httpContext.RequestServices, userToken);
                        if (userToken.Deserialize(authorization.Data, httpContext))
                        {
                            httpContext.User = new ClaimsPrincipal(userToken);
                            return true;
                        }
                    }
                }
            }
            catch
            {

            }
            return false;
        }



        public virtual Result OnAuthorization(AuthorizationFilterContext context, AuthIdentity[] userTokens)
        {
            if (!IsValidate)
            {
                return null;
            }
            if (!Load(context.HttpContext, userTokens))
            {
                return Result.Fail(ErrorType.AuthorizationError.GetDescription(), ErrorType.AuthorizationError);
            }
            return null;
        }





    }

}
